

//#include <dwmapi.h>
//#include <Uxtheme.h>
//#include <winuser.h>

#include <cmath>

//#ifdef __LINUX__
//#include <GL/glx.h>
//#include <X11/Xlib.h>
//#include <X11/Xfuncproto.h>
//#include <X11/Xosdefs.h>
//#include <X11/Xutil.h>
//#endif


#include <SDL2/SDL.h>
#include <SDL2/SDL_syswm.h>
#include <SDL2/SDL_keyboard.h>
#include <SDL2/SDL_shape.h>

#ifdef __LINUX__
#include <X11/Xlib.h>
#include <X11/Xfuncproto.h>
#include <X11/Xosdefs.h>
#include <X11/Xutil.h>
#endif

/*
#ifdef __STRICT_ANSI__
#undef __STRICT_ANSI__
#include <cstdio>
#define __STRICT_ANSI__
#else
#include <cstdio>
#endif
*/
#include <algorithm>

typedef struct _MARGINS
{
    int cxLeftWidth;      // width of left border that retains its size
    int cxRightWidth;     // width of right border that retains its size
    int cyTopHeight;      // height of top border that retains its size
    int cyBottomHeight;   // height of bottom border that retains its size
} MARGINS, *PMARGINS;

#include "MyWindow.h"

#include "GLRenderer.h"

//#include <GL/glx.h>
//#include <X11/extensions/Xrender.h>

//#include "globals.h"

using namespace std;

GLTexture ui_texture1;
GLTexture ui_texture2;
GLTexture font_texture;

//static WNDCLASS win_class;
//static HINSTANCE h_instance;


void GetWindowRect(SDL_Window* window, MyRect& window_rect){
	int pos[2], size[2];
	SDL_GetWindowPosition(window, &pos[0], &pos[1]);
	SDL_GetWindowSize(window, &size[0], &size[1]);

	window_rect.left = pos[0];
	window_rect.right = pos[0] + size[0];
	window_rect.top = pos[1];
	window_rect.bottom = pos[1] + size[1];
}

MyWinFrame::MyWinFrame (float start_x, float start_y, float width, float height, int skin, int zone_size[2]) {

	float corner_pad[2] = { W_CORNER_PAD / (float)zone_size[0], W_CORNER_PAD / (float)zone_size[1]};

	dims_[0] = start_x; dims_[1] = start_y;
	dims_[2] = width;	dims_[3] = height;

	width -= 2.0f * corner_pad[0];
    height -= 2.0f * corner_pad[1];
        
    positions_[0] = start_x;                            positions_[1] = start_y + corner_pad[1];
    tex_coords_[0] = WF_COORDS[skin][2];                tex_coords_[1] = WF_COORDS[skin][3];
        
    positions_[3] = start_x;                            positions_[4] = start_y;
    tex_coords_[2] = WF_COORDS[skin][0];                tex_coords_[3] = WF_COORDS[skin][1];
                
    positions_[6] = start_x + corner_pad[0];            positions_[7] = start_y + corner_pad[1];
    tex_coords_[4] = WF_COORDS[skin][6];                tex_coords_[5] = WF_COORDS[skin][7];
                        
    positions_[9] = start_x + corner_pad[0];            positions_[10] = start_y;
    tex_coords_[6] = WF_COORDS[skin][4];                tex_coords_[7] = WF_COORDS[skin][5];
                                
    positions_[12] = start_x + corner_pad[0] + width;   positions_[13] = start_y + corner_pad[1];
	tex_coords_[8] = WF_COORDS[skin][6];                tex_coords_[9] = WF_COORDS[skin][7];
                                        
	positions_[15] = start_x + corner_pad[0] + width;   positions_[16] = start_y;
	tex_coords_[10] = WF_COORDS[skin][4];               tex_coords_[11] = WF_COORDS[skin][5];
                                        
	positions_[18] = start_x + 2*corner_pad[0] + width; positions_[19] = start_y + corner_pad[1];
	tex_coords_[12] = WF_COORDS[skin][2];               tex_coords_[13] = WF_COORDS[skin][3];
                                                
	positions_[21] = start_x + 2*corner_pad[0] + width;  positions_[22] = start_y;
	tex_coords_[14] = WF_COORDS[skin][0];               tex_coords_[15] = WF_COORDS[skin][1];
                                        
	positions_[24] = positions_[21];                    positions_[25] = positions_[22];
	tex_coords_[16] = tex_coords_[14];                  tex_coords_[17] = tex_coords_[15];
	//              
	positions_[27] = positions_[0];                     positions_[28] = positions_[1] + height;
	tex_coords_[18] = tex_coords_[0];                   tex_coords_[19] = tex_coords_[1];
                                                                
	positions_[30] = positions_[0];                     positions_[31] = positions_[1] + height;
	tex_coords_[20] = tex_coords_[0];                   tex_coords_[21] = tex_coords_[1];
                                                                        
	positions_[33] = positions_[0];                     positions_[34] = positions_[1];
	tex_coords_[22] = tex_coords_[0];                   tex_coords_[23] = tex_coords_[1];
                                                                                
	positions_[36] = positions_[6];                     positions_[37] = positions_[7] + height;
	tex_coords_[24] = tex_coords_[4];                   tex_coords_[25] = tex_coords_[5];
                                                                                        
	positions_[39] = positions_[6];                     positions_[40] = positions_[7];
	tex_coords_[26] = tex_coords_[4];                   tex_coords_[27] = tex_coords_[5];
                                                                                                
	positions_[42] = positions_[12];                    positions_[43] = positions_[13] + height;
	tex_coords_[28] = tex_coords_[8];                   tex_coords_[29] = tex_coords_[9];
                                                                                                        
	positions_[45] = positions_[12];                    positions_[46] = positions_[13];
	tex_coords_[30] = tex_coords_[8];                   tex_coords_[31] = tex_coords_[9];
                                                                                                                
	positions_[48] = positions_[18];                    positions_[49] = positions_[19] + height;
	tex_coords_[32] = tex_coords_[12];                  tex_coords_[33] = tex_coords_[13];
                                                                                                                        
	positions_[51] = positions_[18];                    positions_[52] = positions_[19];
	tex_coords_[34] = tex_coords_[12];                  tex_coords_[35] = tex_coords_[13];
                                                                                                                                
	positions_[54] = positions_[18];                    positions_[55] = positions_[19];
	tex_coords_[36] = tex_coords_[12];                  tex_coords_[37] = tex_coords_[13];
	//                                                                                                                          
	positions_[57] = positions_[27];                    positions_[58] = positions_[28] + corner_pad[1];
	tex_coords_[38] = tex_coords_[2];                   tex_coords_[39] = tex_coords_[3];
                                                                                                                                    
	positions_[60] = positions_[27];                    positions_[61] = positions_[28] + corner_pad[1];
	tex_coords_[40] = tex_coords_[2];                   tex_coords_[41] = tex_coords_[3];
            
	positions_[63] = positions_[27];                    positions_[64] = positions_[28];
	tex_coords_[42] = tex_coords_[18];                  tex_coords_[43] = tex_coords_[19];
                                                                                            
	positions_[66] = positions_[36];                    positions_[67] = positions_[37] + corner_pad[1];
	tex_coords_[44] = tex_coords_[6];                   tex_coords_[45] = tex_coords_[7];
                                                                                                    
	positions_[69] = positions_[36];                    positions_[70] = positions_[37];
    tex_coords_[46] = tex_coords_[24];                  tex_coords_[47] = tex_coords_[25];
                                                                                                            
    positions_[72] = positions_[36] + width;            positions_[73] = positions_[37] + corner_pad[1];
    tex_coords_[48] = tex_coords_[10];                  tex_coords_[49] = tex_coords_[11];
                                                                                                                    
	positions_[75] = positions_[36] + width;            positions_[76] = positions_[37];
	tex_coords_[50] = tex_coords_[8];                   tex_coords_[51] = tex_coords_[9];
                                                                                                                            
	positions_[78] = positions_[48];                    positions_[79] = positions_[49] + corner_pad[1];
	tex_coords_[52] = tex_coords_[14];                  tex_coords_[53] = tex_coords_[15];
                                                                                
	positions_[81] = positions_[48];                    positions_[82] = positions_[49];
	tex_coords_[54] = tex_coords_[12];                  tex_coords_[55] = tex_coords_[13];

	for(int i = 0; i < 28; i++)
    {
		positions_[i * 3 + 2] = 0.0f;
    }

}

void MyWinFrame::UpdateSize(int new_size[2]) {

	float corner_pad[2] = { W_CORNER_PAD / (float)new_size[0], W_CORNER_PAD / (float)new_size[1]};

	float inner_width = dims_[2] - 2.0f * corner_pad[0];
    float inner_height = dims_[3] - 2.0f * corner_pad[1];

        
    positions_[0] = dims_[0];                            		positions_[1] = dims_[1] + corner_pad[1];
    positions_[3] = dims_[0];                            		positions_[4] = dims_[1];
    positions_[6] = dims_[0] + corner_pad[0];            		positions_[7] = dims_[1] + corner_pad[1];
    positions_[9] = dims_[0] + corner_pad[0];            		positions_[10] = dims_[1];
    positions_[12] = dims_[0] + corner_pad[0] + inner_width;	positions_[13] = dims_[1] + corner_pad[1];
	positions_[15] = dims_[0] + corner_pad[0] + inner_width;   	positions_[16] = dims_[1];
	positions_[18] = dims_[0] + 2*corner_pad[0] + inner_width; 	positions_[19] = dims_[1] + corner_pad[1];
	positions_[21] = dims_[0] + 2*corner_pad[0] + inner_width;  positions_[22] = dims_[1];
	positions_[24] = positions_[21];                    		positions_[25] = positions_[22];
	//              
	positions_[27] = positions_[0];                     		positions_[28] = positions_[1] + inner_height;
	positions_[30] = positions_[0];                     		positions_[31] = positions_[1] + inner_height;
	positions_[33] = positions_[0];                     		positions_[34] = positions_[1];
	positions_[36] = positions_[6];                     		positions_[37] = positions_[7] + inner_height;
	positions_[39] = positions_[6];                     		positions_[40] = positions_[7];
	positions_[42] = positions_[12];                    		positions_[43] = positions_[13] + inner_height;
	positions_[45] = positions_[12];                    		positions_[46] = positions_[13];
	positions_[48] = positions_[18];                   			positions_[49] = positions_[19] + inner_height;
	positions_[51] = positions_[18];                    		positions_[52] = positions_[19];
	positions_[54] = positions_[18];                    		positions_[55] = positions_[19];
	//                                                                                                                          
	positions_[57] = positions_[27];                    		positions_[58] = positions_[28] + corner_pad[1];
	positions_[60] = positions_[27];                    		positions_[61] = positions_[28] + corner_pad[1];
	positions_[63] = positions_[27];                    		positions_[64] = positions_[28];
	positions_[66] = positions_[36];                    		positions_[67] = positions_[37] + corner_pad[1];
	positions_[69] = positions_[36];                    		positions_[70] = positions_[37];
    positions_[72] = positions_[36] + inner_width;				positions_[73] = positions_[37] + corner_pad[1];
	positions_[75] = positions_[36] + inner_width;				positions_[76] = positions_[37];
	positions_[78] = positions_[48];                    		positions_[79] = positions_[49] + corner_pad[1];
	positions_[81] = positions_[48];                    		positions_[82] = positions_[49];

}

void MyWinFrame::UpdateSize(float start_x, float start_y, float width, float height, int zone_size[2]) {

	float corner_pad[2] = { W_CORNER_PAD / (float)zone_size[0], W_CORNER_PAD / (float)zone_size[1]};

	dims_[0] = start_x; dims_[1] = start_y;
	dims_[2] = width;	dims_[3] = height;

	width -= 2.0f * corner_pad[0];
    height -= 2.0f * corner_pad[1];
        
    positions_[0] = start_x;                            positions_[1] = start_y + corner_pad[1];
    positions_[3] = start_x;                            positions_[4] = start_y;
    positions_[6] = start_x + corner_pad[0];            positions_[7] = start_y + corner_pad[1];
    positions_[9] = start_x + corner_pad[0];            positions_[10] = start_y;
    positions_[12] = start_x + corner_pad[0] + width;   positions_[13] = start_y + corner_pad[1];
	positions_[15] = start_x + corner_pad[0] + width;   positions_[16] = start_y;
	positions_[18] = start_x + 2*corner_pad[0] + width; positions_[19] = start_y + corner_pad[1];
	positions_[21] = start_x + 2*corner_pad[0] + width;  positions_[22] = start_y;
	positions_[24] = positions_[21];                    positions_[25] = positions_[22];
	//              
	positions_[27] = positions_[0];                     positions_[28] = positions_[1] + height;
	positions_[30] = positions_[0];                     positions_[31] = positions_[1] + height;
	positions_[33] = positions_[0];                     positions_[34] = positions_[1];
	positions_[36] = positions_[6];                     positions_[37] = positions_[7] + height;
	positions_[39] = positions_[6];                     positions_[40] = positions_[7];
	positions_[42] = positions_[12];                    positions_[43] = positions_[13] + height;
	positions_[45] = positions_[12];                    positions_[46] = positions_[13];
	positions_[48] = positions_[18];                    positions_[49] = positions_[19] + height;
	positions_[51] = positions_[18];                    positions_[52] = positions_[19];
	positions_[54] = positions_[18];                    positions_[55] = positions_[19];
	//                                                                                                                          
	positions_[57] = positions_[27];                    positions_[58] = positions_[28] + corner_pad[1];
	positions_[60] = positions_[27];                    positions_[61] = positions_[28] + corner_pad[1];
	positions_[63] = positions_[27];                    positions_[64] = positions_[28];
	positions_[66] = positions_[36];                    positions_[67] = positions_[37] + corner_pad[1];
	positions_[69] = positions_[36];                    positions_[70] = positions_[37];
    positions_[72] = positions_[36] + width;            positions_[73] = positions_[37] + corner_pad[1];
	positions_[75] = positions_[36] + width;            positions_[76] = positions_[37];
	positions_[78] = positions_[48];                    positions_[79] = positions_[49] + corner_pad[1];
	positions_[81] = positions_[48];                    positions_[82] = positions_[49];

}


void MyWinFrame::Draw() {

	//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	Renderer::SwitchOwnTexture(DIFFUSEMAP_SLOT, ui_texture1);

	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	//glBlendFunc(GL_SRC_COLOR, GL_DST_ALPHA);
	//glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
    glEnable(GL_BLEND);

	glEnableVertexAttribArray(Renderer::render_state->current_program->attribute(POSITION_ATTRIBUTE));
	glVertexAttribPointer(Renderer::render_state->current_program->attribute(POSITION_ATTRIBUTE), 3, GL_FLOAT, GL_FALSE, 0, positions_);
		
	glEnableVertexAttribArray(Renderer::render_state->current_program->attribute(UV_ATTRIBUTE));
	glVertexAttribPointer(Renderer::render_state->current_program->attribute(UV_ATTRIBUTE), 2, GL_FLOAT, GL_FALSE, 0, tex_coords_);
	
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 28);

	glDisableVertexAttribArray(Renderer::render_state->current_program->attribute(UV_ATTRIBUTE));
	glDisableVertexAttribArray(Renderer::render_state->current_program->attribute(POSITION_ATTRIBUTE));

	glDisable(GL_BLEND);

}

MyBaseElement::MyBaseElement(float start_x, float start_y, float size_x, float size_y, int zone_size[2]) {
		dims_[0] = start_x;	dims_[1] = start_y;
		dims_[2] = size_x;	dims_[3] = size_y;

		dims_px_[0] = static_cast<int>(dims_[0] * zone_size[0] * 0.5f + zone_size[0] * 0.5f);
		dims_px_[1] = static_cast<int>(dims_[1] * zone_size[1] * 0.5f + zone_size[1] * 0.5f);
		dims_px_[2] = static_cast<int>(dims_[2] * zone_size[0] * 0.5f);
		dims_px_[3] = static_cast<int>(dims_[3] * zone_size[1] * 0.5f);

		resizable_ = true;
	}

MyBaseElement::MyBaseElement() {
		dims_[0] = 0.0f;	dims_[1] = 0.0f;
		dims_[2] = 1.0f;	dims_[3] = 1.0f;

		dims_px_[0] = static_cast<int>(dims_[0] * 800 * 0.5f + 800 * 0.5f);
		dims_px_[1] = static_cast<int>(dims_[1] * 800 * 0.5f + 800 * 0.5f);
		dims_px_[2] = static_cast<int>(dims_[2] * 800 * 0.5f);
		dims_px_[3] = static_cast<int>(dims_[3] * 800 * 0.5f);

		resizable_ = true;
	}

MyBaseElement::~MyBaseElement() {

}

void MyBaseElement::Resize(int zone_size[2]) {

		dims_px_[0] = static_cast<int>(dims_[0] * zone_size[0] * 0.5f + zone_size[0] * 0.5f);
		dims_px_[1] = static_cast<int>(dims_[1] * zone_size[1] * 0.5f + zone_size[1] * 0.5f);
		dims_px_[2] = static_cast<int>(dims_[2] * zone_size[0] * 0.5f);
		dims_px_[3] = static_cast<int>(dims_[3] * zone_size[1] * 0.5f);

	}

void MyBaseElement::Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]) {

		dims_[0] = start_x;	dims_[1] = start_y;
		dims_[2] = size_x;	dims_[3] = size_y;

		dims_px_[0] = static_cast<int>(dims_[0] * zone_size[0] * 0.5f + zone_size[0] * 0.5f);
		dims_px_[1] = static_cast<int>(dims_[1] * zone_size[1] * 0.5f + zone_size[1] * 0.5f);
		dims_px_[2] = static_cast<int>(dims_[2] * zone_size[0] * 0.5f);
		dims_px_[3] = static_cast<int>(dims_[3] * zone_size[1] * 0.5f);

	}

bool MyBaseElement::Check(float x, float y) {
		
		if((x >= dims_[0]) &&
			(x <= dims_[0] + dims_[2]) &&
			(y >= dims_[1]) &&
			(y <= dims_[1] + dims_[3]))
		{
			return true;
		}

		return false;
	}

MyTypeMesh::MyTypeMesh(string text, float start_x, float start_y, float scale, int zone_size[2]) : MyBaseElement(start_x, start_y, 0.0f, 0.0f, zone_size), text_(text), scale_(scale){

	//text_ = text;

	//float aspect = zone_size[0] / (float) zone_size[1];

	//cout << "text length : " << text_.length() << endl;

	float pad = 0.0f;

	positions_.reserve(text_.length() * 4 * 3);
	tex_coords_.reserve(text_.length() * 4 * 2);

	num_tris_ = text_.length() * 4;

	for(unsigned int i = 0; i < text_.length(); i++)
    {
            
		int char_code = text_[i];
        
        if(char_code < 0)
        {
			char_code += 256;
			//char_code = -char_code +
        }

		//cout << char_code << endl;
            
        int shell_y = 16 - (char_code - 32) / 16;
        int shell_x = (char_code - 32) % 16;

		//cout << "shell_x: " << shell_x << endl;
		//cout << "shell_y: " << shell_y << endl;
            
		positions_.push_back(start_x + pad * scale * (700.0f / zone_size[0]));
		positions_.push_back(start_y + (64.0f*scale * (700.0f / zone_size[1]))/FONT_TEX_SIZE);
		positions_.push_back(0.0f);

        //tex_coords_[i*4*2 + 0] = (shell_x) / 16.0f;
        //tex_coords_[i*4*2 + 1] = (shell_y) / 16.0f;
		tex_coords_.push_back((shell_x) / 16.0f);
		tex_coords_.push_back((shell_y) / 16.0f);

		

		positions_.push_back(positions_[i*4*3 + 0]);
		positions_.push_back(start_y);
        positions_.push_back(0.0f);

        //tex_coords_[i*4*2 + 2] = (shell_x) / 16.0f;
        //tex_coords_[i*4*2 + 3] = (shell_y) / 16.0f - 1.0f/16.0f;
		tex_coords_.push_back((shell_x) / 16.0f);
		tex_coords_.push_back((shell_y) / 16.0f - 1.0f/16.0f);

        pad += paddings[char_code - 32] / FONT_TEX_SIZE;

		positions_.push_back(start_x + pad * scale * (700.0f / zone_size[0]));
		positions_.push_back(start_y + (64.0f*scale * (700.0f / zone_size[1]))/FONT_TEX_SIZE);
        positions_.push_back(0.0f);

        //tex_coords_[i*4*2 + 4] = (shell_x) / 16.0f + paddings[char_code - 32] / FONT_TEX_SIZE;
        //tex_coords_[i*4*2 + 5] = (shell_y) / 16.0f;
		tex_coords_.push_back((shell_x) / 16.0f + paddings[char_code - 32] / FONT_TEX_SIZE);
		tex_coords_.push_back((shell_y) / 16.0f);
            
		positions_.push_back(positions_[i*4*3 + 6]);
		positions_.push_back(start_y);
        positions_.push_back(0.0f);

        //tex_coords_[i*4*2 + 6] = (shell_x) / 16.0f + paddings[char_code - 32] / FONT_TEX_SIZE;
        //tex_coords_[i*4*2 + 7] = (shell_y) / 16.0f - 1.0f/16.0f;
		tex_coords_.push_back((shell_x) / 16.0f + paddings[char_code - 32] / FONT_TEX_SIZE);
		tex_coords_.push_back((shell_y) / 16.0f - 1.0f/16.0f);

        }

		//if(text_.length() != 0)
		//{
		//tex_coords_._Mylast = &tex_coords_[text_.length() * 4 * 2 + 7];
		//tex_coords_._Myend = &tex_coords_[text_.length() * 4 * 2 + 8];
		//}

		center_x_ = start_x + pad * scale * 0.5f * (700.0f / zone_size[0]);
		center_y_ = start_y + (32.0f*scale* (700.0f / zone_size[1]))/FONT_TEX_SIZE;

		//size_px_[0] = pad;
		//size_px_[1] = 64;

		dims_[2] = pad * scale * (700.0f / zone_size[0]);
		//dims_[3] = (64.0f*scale* (700.0f / zone_size[1]))/FONT_TEX_SIZE;
		dims_[3] = (40.0f*scale* (700.0f / zone_size[1]))/FONT_TEX_SIZE;

		dims_px_[2] = static_cast<int>(dims_[2] * zone_size[0] * 1.0f);
		dims_px_[3] = static_cast<int>(dims_[3] * zone_size[1] * 1.0f);

		resizable_ = false;
}

MyTypeMesh::MyTypeMesh() : num_tris_(0), center_x_(0.0f), center_y_(0.0f), scale_(0.8f){

	

}

MyTypeMesh::MyTypeMesh(const MyTypeMesh& mesh_to_copy) : MyBaseElement(mesh_to_copy),
														  text_(mesh_to_copy.text_),
														  positions_(mesh_to_copy.positions_),
														  tex_coords_(mesh_to_copy.tex_coords_),
														  num_tris_(mesh_to_copy.num_tris_),
														  center_x_(mesh_to_copy.center_x_),
														  center_y_(mesh_to_copy.center_y_),
														  scale_(mesh_to_copy.scale_) {




}

MyTypeMesh::~MyTypeMesh() {

}

void MyTypeMesh::Move(float new_x, float new_y, int zone_size[2]) {

	float dx = new_x - dims_[0];
	float dy = new_y - dims_[1];
	
	dims_[0] = new_x;
	dims_[1] = new_y;

	center_x_ += dx;
	center_y_ += dy;

	//cout << "dx " << dx << endl;

	for(auto point = positions_.begin(); point != positions_.end(); point += 3)
	{
		point[0] += dx;
		point[1] += dy;
	}

	float mx = ((float)dims_px_[2] / zone_size[0]) / dims_[2];
	dims_[2] *= mx;
	float my = ((float)dims_px_[3] / zone_size[1]) / dims_[3];
	dims_[3] *= my;
	

	center_x_ = (center_x_ - dims_[0]) * mx + dims_[0];
	center_y_ = (center_y_ - dims_[1]) * my + dims_[1];

	for(auto point = positions_.begin(); point != positions_.end(); point += 3)
	{
		point[0] = (point[0] - dims_[0]) * mx + dims_[0];
		point[1] = (point[1] - dims_[1]) * my + dims_[1];
	}

	//dims_px_[2] = dims_[2] * zone_size[0];
	//dims_px_[3] = dims_[3] * zone_size[1];

}

void MyTypeMesh::Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]) {

	//MyBaseElement::Resize(start_x, start_y, size_x, size_y, zone_size);

	Move(start_x, start_y, zone_size);

}

void MyTypeMesh::Centrate() {

	float dx = dims_[0] - center_x_;
	float dy = dims_[1] - center_y_;

	center_x_ += dx;
	center_y_ += dy;

	for(auto point = positions_.begin(); point != positions_.end(); point += 3)
	{
		point[0] += dx;
		point[1] += dy;
	}

}

bool MyTypeMesh::Check(float x, float y)
{
	if(	(x >= dims_[0]) &&
		(x <= dims_[0] + dims_[2]) &&
		(y >= dims_[1]) &&
		(y <= dims_[1] + dims_[3] + 0.015 * scale_))
	{
		return true;
	}

	return false;
}

void MyTypeMesh::Draw() {

	if(positions_.empty())
	{
		return;
	}

	Renderer::SwitchOwnTexture(DIFFUSEMAP_SLOT, font_texture);

	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	//glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
    glEnable(GL_BLEND);

	glEnableVertexAttribArray(Renderer::render_state->current_program->attribute(POSITION_ATTRIBUTE));
	glVertexAttribPointer(Renderer::render_state->current_program->attribute(POSITION_ATTRIBUTE), 3, GL_FLOAT, GL_FALSE, 0, &positions_[0]);
		
	glEnableVertexAttribArray(Renderer::render_state->current_program->attribute(UV_ATTRIBUTE));
	glVertexAttribPointer(Renderer::render_state->current_program->attribute(UV_ATTRIBUTE), 2, GL_FLOAT, GL_FALSE, 0, &tex_coords_[0]);
	
		//glScissor(dims_px_[0], dims_px_[1], dims_px_[2], dims_px_[3]);
		//glEnable(GL_SCISSOR_TEST);
		
	glDrawArrays(GL_TRIANGLE_STRIP, 0, num_tris_);

		//glDisable(GL_SCISSOR_TEST);

	glDisableVertexAttribArray(Renderer::render_state->current_program->attribute(UV_ATTRIBUTE));
	glDisableVertexAttribArray(Renderer::render_state->current_program->attribute(POSITION_ATTRIBUTE));

	glDisable(GL_BLEND);

}


void MyLinearLayout::Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]) {
		MyBaseElement::Resize(start_x, start_y, size_x, size_y, zone_size);

		float spacing;
		float filled_space = 0.0f;
		float l;
		if(vertical_)
		{
			spacing = 8.0f / zone_size[1];
			l = size_y - spacing * (elements_.size() + 1);
			for(auto element = elements_.begin(); element != elements_.end(); element++)
			{
				
				if((*element)->resizable())
				{
					filled_space += (*element)->dims()[3];
				} else
				{
					l -= (*element)->dims()[3];
				}
			}
		} else
		{
			spacing = 8.0f / zone_size[0];
			l = size_x - spacing * (elements_.size() + 1);
			for(auto element = elements_.begin(); element != elements_.end(); element++)
			{
				
				if((*element)->resizable())
				{
					filled_space += (*element)->dims()[2];
				} else
				{
					l -= (*element)->dims()[2];
				}
			}
		}

		float mult =  l / filled_space;

		float pad = 0.0f;

		if(vertical_)
		{
			//pad = start_y + spacing;
			pad = start_y + size_y - spacing;

			//elements_[0]->Resize(start_x, pad, size_x, elements_[0]->dims()[3]*mult, zone_size);
			//pad = dims_[1] + dims_[3] - elements_[0]->dims()[3] - spacing;
			//pad = dims_[1] + dims_[3] - spacing;
			
			for(auto element = elements_.begin(); element != elements_.end(); element++)
			//for(auto element = elements_.end() - 1; element >= elements_.begin(); element--)
			{
				//(*element)->Resize(start_x, pad, size_x, (*element)->dims()[3]*mult, zone_size);
				//pad -= (*element)->dims()[3] + spacing;

				(*element)->Resize(start_x, 1.0f, size_x, (*element)->dims()[3]*mult, zone_size);
				pad -= ((*element)->dims()[3] + spacing);
				(*element)->Resize(start_x, pad, size_x, (*element)->dims()[3], zone_size);
			}
		} else
		{
			pad = start_x + spacing;
			for(auto element = elements_.begin(); element != elements_.end(); element++)
			{
				(*element)->Resize(pad, start_y, (*element)->dims()[2]*mult, size_y, zone_size);
				pad += (*element)->dims()[2] + spacing;
			}
		}
	}
/*
void DisplayErrorMessage()
{
    LPVOID lpMsgBuf;
 
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        GetLastError(),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
        (LPTSTR) &lpMsgBuf,
        0,
        NULL
   );
 
    MessageBox(NULL, (LPCTSTR)lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION);
    LocalFree(lpMsgBuf);
}
*/
/*********************************************************************************************************************/

void MyBaseWindow::Init(string title) {

		dims_[0] = -1.0f; dims_[1] = -1.0f;
		dims_[2] = 2.0f; dims_[3] = 2.0f;

		/*int pos[2], size[2];
		SDL_GetWindowPosition(window_, &pos[0], &pos[1]);
		SDL_GetWindowSize(window_, &size[0], &size[1]);

		window_rect_.left = pos[0];
		window_rect_.right = pos[0] + size[0];
		window_rect_.top = pos[1];
		window_rect_.bottom = pos[1] + size[1];*/
		GetWindowRect(window_, window_rect_);

		
		window_size_[0] = window_rect_.right - window_rect_.left;
		window_size_[1] = window_rect_.bottom - window_rect_.top;

		drag_zone_[0] = -1.0f;
		drag_zone_[1] = 1.0f - 48.0f / window_size_[1];
		drag_zone_[2] = 1.0f;
		drag_zone_[3] = 1.0f;

		//std::cout << "drag_zone :    " << window_rect_.bottom - window_rect_.top << std::endl;

		resize_zone_left_[0] = -1.0f;
		resize_zone_left_[1] = -1.0f;
		resize_zone_left_[2] = -1.0f + 12.0f / window_size_[0];
		resize_zone_left_[3] = 1.0f;

		resize_zone_right_[0] = 1.0f - 12.0f / window_size_[0];
		resize_zone_right_[1] = -1.0f;
		resize_zone_right_[2] = 1.0f;
		resize_zone_right_[3] = 1.0f;

		resize_zone_bottom_[0] = -1.0f;
		resize_zone_bottom_[1] = -1.0f;
		resize_zone_bottom_[2] = 1.0f;
		resize_zone_bottom_[3] = -1.0f + 12.0f / window_size_[1];

		resize_zone_top_[0] = -1.0f;
		resize_zone_top_[1] = 1.0f - 12.0f / window_size_[1];
		resize_zone_top_[2] = 1.0f;
		resize_zone_top_[3] = 1.0f;

		resize_ = 9;
		drag_enabled_ = false;
		update_needed_ = false;

		click.AssignFunction(this, &MyBaseWindow::OnClick);
		move.AssignFunction(this, &MyBaseWindow::OnMove);
		release.AssignFunction(this, &MyBaseWindow::OnRelease);
		key_press.AssignFunction(this, &MyBaseWindow::OnKeyPress);



		//frame_ = new MyWinFrame(dims_[0], dims_[1], dims_[2], dims_[3], 0, window_size_);
		frame_ = MyWinFrame(dims_[0], dims_[1], dims_[2], dims_[3], 0, window_size_);

		close_button_ = MyButton("X", 1.0f - 110.0f/window_size_[0],
									1.0f - 40.0f/window_size_[1],
									100.0f/window_size_[0],
									45.0f/window_size_[1],
									window_size_);

		quit.AssignFunction(this, &MyBaseWindow::Quit);
		quit.Connect(close_button_.press_signal());

		full_scr_button_ = MyButton( "\177", 1.0f - 180.0f/window_size_[0],
									1.0f - 40.0f/window_size_[1],
									70.0f/window_size_[0],
									45.0f/window_size_[1],
									window_size_);
		full_scr.AssignFunction(this, &MyBaseWindow::GoFullScreen);
		full_scr.Connect(full_scr_button_.press_signal());

		max_min_button_ = MyButton("\227", 1.0f - 250.0f/window_size_[0],
									1.0f - 40.0f/window_size_[1],
									70.0f/window_size_[0],
									45.0f/window_size_[1],
									window_size_);

		minimize.AssignFunction(this, &MyBaseWindow::Minimize);
		minimize.Connect(max_min_button_.press_signal());

		wnd_rect_bfr_max_.bottom = 0;

		//title_.reset(new MyTypeMesh(title, -1.0f + 32.0f/window_size_[0], 1.0f - 40.0f/window_size_[1], 0.8f, window_size_));
		title_ = MyTypeMesh(title, -1.0f + 32.0f/window_size_[0], 1.0f - 40.0f/window_size_[1], 0.8f, window_size_);

		OnMove(0.0f, 0.0f);
	}


SDL_GLContext MyBaseWindow::shared_gl_context = nullptr;

//MyBaseWindow::MyBaseWindow(int size_x, int size_y, char flags, long (CALLBACK *win_proc)(HWND, unsigned int, unsigned int, long)) {
MyBaseWindow::MyBaseWindow(string title, int size_x, int size_y, char flags) : hidden_(true){
	/*
	InitWndClass();

	win_class_ = win_class;

    win_class_.lpfnWndProc = win_proc;
	
	class_name_ = "Wnd_";
	class_name_ += id_;
	id_++;

	win_class_.lpszClassName = class_name_.c_str();

	RegisterClass (&win_class_);

	window_handle_ = CreateWindow (
		class_name_.c_str(), "OpenGL Window", 
		!WS_BORDER | WS_POPUP | !WS_VISIBLE,
	  CW_USEDEFAULT, CW_USEDEFAULT, size_x, size_y,
      NULL, NULL, win_class_.hInstance, NULL);
	*/

	window_ = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
			size_x, size_y, SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_HIDDEN);

	//window_ = SDL_CreateShapedWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
	//		size_x, size_y, SDL_WINDOW_OPENGL);

	flags_.set = flags;

#ifdef WIN32
	HMODULE hDWMApi = GetModuleHandle("Dwmapi.dll");
	typedef BOOL (WINAPI *lpfnDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS*);
	lpfnDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea;
	pDwmExtendFrameIntoClientArea = (lpfnDwmExtendFrameIntoClientArea)GetProcAddress(hDWMApi, "DwmExtendFrameIntoClientArea");

	/*typedef BOOL (WINAPI *lpfnDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND *pBlurBehind);
	lpfnDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow;
	pDwmEnableBlurBehindWindow = (lpfnDwmEnableBlurBehindWindow)GetProcAddress(hDWMApi, "DwmEnableBlurBehindWindow");*/

	MARGINS margins = {2, 2, 2, 2};

	SDL_SysWMinfo i;
	SDL_VERSION(&i.version);
	if(SDL_GetWindowWMInfo(window_, &i))
	{
		pDwmExtendFrameIntoClientArea(i.info.win.window, &margins);
	}


/*
	if(flags_.blur_behind)
	{
		DWM_BLURBEHIND bb = {0};
		bb.dwFlags = DWM_BB_ENABLE;
		bb.fEnable = true;
		bb.hRgnBlur = NULL;
		pDwmEnableBlurBehindWindow(window_handle_, &bb);
	}
*/
	FreeLibrary(hDWMApi);
#else
#ifdef __LINUX__
	/*SDL_SysWMinfo i;
	SDL_VERSION(&i.version);
	if(SDL_GetWindowWMInfo(window_, &i))
	{
		XEvent ev;

		memset(&ev, 0, sizeof (ev));

		ev.xclient.type = ClientMessage;
		ev.xclient.window = i.info.x11.window;
		ev.xclient.message_type = XInternAtom(i.info.x11.display, "_NET_WM_MOVERESIZE", false);
		ev.xclient.format = 32;
		ev.xclient.data.l[0] = 0;
		ev.xclient.data.l[1] = 0;
		ev.xclient.data.l[2] = 8;
		ev.xclient.data.l[3] = 0;
		ev.xclient.data.l[4] = 0;
		XSendEvent(i.info.x11.display, i.info.x11.window, False, NoEventMask, &ev);


	}*/
#endif
#endif

	/*shape = SDL_CreateRGBSurface(0, 500,500, 32,
            0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
	box.x = 0;
	box.y = 0;
	box.h =  300;
	box.w = 499;
	SDL_PixelFormat f = *shape->format;
	SDL_FillRect(shape,&box,SDL_MapRGBA(shape->format, 0, 0, 0, 1));
*/


	//SDL_WindowShapeMode mode;
	//mode.mode = ShapeModeDefault;
	//int res = SDL_SetWindowShape(window_, shape, &mode);
	//cout << "res = " << res << endl;
	Init(title);
	
	//Renderer::EnableOpenGL(window_handle_, &device_handle_, &gl_context_handle_);

	if(!shared_gl_context)
	{
		shared_gl_context = SDL_GL_CreateContext(window_);
		//SDL_GL_MakeCurrent(window_, shared_gl_context);

		GLenum glew_err = glewInit();
		if (glew_err != GLEW_OK) {
			fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(glew_err));
		}

		ui_texture1 = Renderer::LoadTGATexture("textures/ui_texture256.tga");
		ui_texture2 = Renderer::LoadTGATexture("textures/icons.tga");
		font_texture = Renderer::LoadTGATexture("textures/font_texture4.tga");
	}
	//SDL_GL_MakeCurrent(window_, gl_context_);

	/*GLenum glew_err = glewInit();
	if (glew_err != GLEW_OK) {
		fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(glew_err));
	}*/

	//ShowWindow(window_handle_, SW_HIDE);
	//SetFocus(window_handle_);

}


void MyBaseWindow::Draw() {

	//wglMakeCurrent(device_handle_, gl_context_handle_);
	Renderer::SetViewport(0, 0, window_size_[0], window_size_[1]);

	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_BLEND);

	frame_.Draw();

	if(flags_.close_enabled)
	{
		close_button_.Draw();
	}
	if(flags_.full_scr_enabled)
	{
		full_scr_button_.Draw();
	}
	if(flags_.minimize_enabled)
	{
		max_min_button_.Draw();
	}

	title_.Draw();
		
}

void MyBaseWindow::SetTopMost(){
#ifdef WIN32
		SDL_SysWMinfo i;
		SDL_VERSION(&i.version);
		if(SDL_GetWindowWMInfo(window_, &i))
		{
			SetWindowPos(i.info.win.window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
		}
#endif
#ifdef __LINUX__

#endif
	}

int MyBaseWindow::OnMove(float dx, float dy) {

		if(!focused() && !update_needed_)
		{
			return -1;
		}

		if(drag_enabled_ && wnd_rect_bfr_max_.bottom == 0)
		{
			//std::cout << "dragging!!! : " << dx << " " << dy << std::endl;

			int new_x = static_cast<int>(std::round((float)window_rect_.left + dx * (float)window_size_[0])),
				new_y = static_cast<int>(std::round((float)window_rect_.top + dy * (float)window_size_[1]));

/*#ifdef __LINUX__
			SDL_SysWMinfo i;
			SDL_VERSION(&i.version);
			if(SDL_GetWindowWMInfo(window_, &i))
			{
				XMoveWindow(i.info.x11.display, i.info.x11.window, new_x, new_y);

			}
#else*/
			//SDL_SetWindowSize(window_, 10, 10);
			SDL_SetWindowPosition(window_, new_x, new_y);
			//SDL_SetWindowSize(window_, window_size_[0], window_size_[1]);
//#endif

			window_rect_.left = new_x;
			window_rect_.right = new_x + window_size_[0];
			window_rect_.top = new_y;
			window_rect_.bottom = new_y + window_size_[1];


			update_needed_ = true;
		}

		int new_size_x, new_size_y;

		if(resize_)
		{
			update_needed_ = true;
		}

		if(flags_.resize_enabled && wnd_rect_bfr_max_.bottom == 0)
		switch(resize_)
		{
		case LEFT:
			window_rect_.left += static_cast<long>(std::round(dx * window_size_[0]));
			new_size_x = (window_rect_.right - window_rect_.left);
			if(new_size_x < 200)
			{
				return 0;
			}
			//SetWindowPos(window_handle_, 0, window_rect_.left, window_rect_.top, new_size_x, window_size_[1], 0);
			SDL_SetWindowPosition(window_, window_rect_.left, window_rect_.top);
			SDL_SetWindowSize(window_, new_size_x, window_size_[1]);
			break;
		case RIGHT:
			window_rect_.right += static_cast<long>(std::round(dx * window_size_[0]));
			new_size_x = (window_rect_.right - window_rect_.left);
			if(new_size_x < 200)
			{
				return 0;
			}
			//SetWindowPos(window_handle_, 0, window_rect_.left, window_rect_.top, new_size_x, window_size_[1], 0);
			//SDL_SetWindowPosition(window_, window_rect_.left, window_rect_.top);
			SDL_SetWindowSize(window_, new_size_x, window_size_[1]);
			break;
		case BOTTOM:
			window_rect_.bottom += static_cast<long>(std::round(dy * window_size_[1]));
			new_size_y = (window_rect_.bottom - window_rect_.top);
			if(new_size_y < 200)
			{
				return 0;
			}
			//SetWindowPos(window_handle_, 0, window_rect_.left, window_rect_.top, window_size_[0], new_size_y, 0);
			//SDL_SetWindowPosition(window_, window_rect_.left, window_rect_.top);
			SDL_SetWindowSize(window_, window_size_[0], new_size_y);
			break;
		case TOP:
			window_rect_.top += static_cast<long>(std::round(dy * window_size_[1]));
			new_size_y = (window_rect_.bottom - window_rect_.top);
			if(new_size_y < 200)
			{
				return 0;
			}
			//SetWindowPos(window_handle_, 0, window_rect_.left, window_rect_.top, window_size_[0], new_size_y, 0);
			SDL_SetWindowPosition(window_, window_rect_.left, window_rect_.top);
			SDL_SetWindowSize(window_, window_size_[0], new_size_y);
			break;

		}


		window_size_[0] = window_rect_.right - window_rect_.left;
		window_size_[1] = window_rect_.bottom - window_rect_.top;

		if(resize_)
		{
			frame_.UpdateSize(window_size_);

			close_button_.Resize(	1.0f - 110.0f/window_size_[0],
									1.0f - 40.0f/window_size_[1],
									98.0f/window_size_[0],
									48.0f/window_size_[1],
									window_size_);

			full_scr_button_.Resize(	1.0f - 180.0f/window_size_[0],
										1.0f - 40.0f/window_size_[1],
										70.0f/window_size_[0],
										48.0f/window_size_[1],
										window_size_);

			max_min_button_.Resize(	1.0f - 250.0f/window_size_[0],
										1.0f - 40.0f/window_size_[1],
										70.0f/window_size_[0],
										48.0f/window_size_[1],
										window_size_);
			title_.Move(	-1.0f + 32.0f/window_size_[0],
							1.0f - 40.0f/window_size_[1], 
							window_size_);
		}
		
		
		resize_zone_left_[2] = -1.0f + 12.0f / window_size_[0];
		resize_zone_right_[0] = 1.0f - 12.0f / window_size_[0];
		resize_zone_bottom_[3] = -1.0f + 12.0f / window_size_[1];
		resize_zone_top_[1] = 1.0f - 12.0f / window_size_[1];
		drag_zone_[1] = 1.0f - 48.0f / window_size_[1];

		return 0;
}

int MyBaseWindow::OnClick(float x, float y) {
		if(!focused())
		{
			return -1;
		}

		//std::cout << "clicked!!! : " << x << " " << y << std::endl;

		if(flags_.close_enabled)
		{
			close_button_.Check(x, y);
		}
		if(flags_.full_scr_enabled)
		{
			full_scr_button_.Check(x, y);
		}
		if(flags_.minimize_enabled)
		{
			max_min_button_.Check(x, y);
		}

		if(close_button_.pressed() || max_min_button_.pressed() || full_scr_button_.pressed())
		{
			return 0;
		}
		
		if((x >= resize_zone_left_[0]) &&
			(x <= resize_zone_left_[2]) &&
			(y >= resize_zone_left_[1]) &&
			(y <= resize_zone_left_[3]))
		{
			resize_ = LEFT;
			//std::cout << "resize!!! : " << x << " " << y << std::endl;
		}
		
		if((x >= resize_zone_right_[0]) &&
			(x <= resize_zone_right_[2]) &&
			(y >= resize_zone_right_[1]) &&
			(y <= resize_zone_right_[3]))
		{
			resize_ = RIGHT;
			//std::cout << "resize!!! : " << x << " " << y << std::endl;
		}
				
		if((x >= resize_zone_bottom_[0]) &&
			(x <= resize_zone_bottom_[2]) &&
			(y >= resize_zone_bottom_[1]) &&
			(y <= resize_zone_bottom_[3]))
		{
			resize_ = BOTTOM;
			//std::cout << "resize!!! : " << x << " " << y << std::endl;
		}

		if((x >= resize_zone_top_[0]) &&
			(x <= resize_zone_top_[2]) &&
			(y >= resize_zone_top_[1]) &&
			(y <= resize_zone_top_[3]))
		{
			resize_ = TOP;
			//std::cout << "resize!!! : " << x << " " << y << std::endl;
		}

		if(resize_ == 0 || resize_ == 9)
		if((x >= drag_zone_[0]) &&
			(x <= drag_zone_[2]) &&
			(y >= drag_zone_[1]) &&
			(y <= drag_zone_[3]))
		{
			drag_enabled_ = true;
			//std::cout << "draggggg!!! : " << x << " " << y << std::endl;
		}


		return 0;
}

int MyBaseWindow::OnRelease(float x, float y) {

		if(!focused())
		{
			return -1;
		}

		drag_enabled_ = false;

		window_size_[0] = window_rect_.right - window_rect_.left;
		window_size_[1] = window_rect_.bottom - window_rect_.top;
		switch(resize_)
		{
		case LEFT:
			if(window_size_[0] < 200)
			{
				window_rect_.left = window_rect_.right - 200;
			}
			break;
		case RIGHT:
			if(window_size_[0] < 200)
			{
				window_rect_.right = window_rect_.left + 200;
			}
			break;
		case TOP:
			if(window_size_[1] < 200)
			{
				window_rect_.top = window_rect_.bottom - 200;
			}
			break;
		case BOTTOM:
			if(window_size_[1] < 200)
			{
				window_rect_.bottom = window_rect_.top + 200;
			}
			break;

		}

		resize_ = 0;

		window_size_[0] = window_rect_.right - window_rect_.left;
		window_size_[1] = window_rect_.bottom - window_rect_.top;

		//SetWindowPos(window_handle_, 0, window_rect_.left, window_rect_.top, window_size_[0], window_size_[1], 0);
		SDL_SetWindowPosition(window_, window_rect_.left, window_rect_.top);
		SDL_SetWindowSize(window_, window_size_[0], window_size_[1]);

		if(flags_.close_enabled)
		{
			close_button_.Check(x, y);
		}
		if(flags_.full_scr_enabled)
		{
			full_scr_button_.Check(x, y);
		}
		if(flags_.minimize_enabled)
		{
			max_min_button_.Check(x, y);
		}

		return 0;
	}


int MyBaseWindow::GoFullScreen() {

		if(wnd_rect_bfr_max_.bottom == 0)
		{
			GetWindowRect(window_, wnd_rect_bfr_max_);
			//const SDL_VideoInfo* info = SDL_GetVideoInfo();

			int screencx = GetSystemMetrics(SM_CXSCREEN);
			int screency = GetSystemMetrics(SM_CYMAXIMIZED) - 16;
			SDL_SetWindowPosition(window_, 0, 0);
			SDL_SetWindowSize(window_, screencx, screency);

		} else
		{
			SDL_SetWindowPosition(window_, wnd_rect_bfr_max_.left, wnd_rect_bfr_max_.top);
			SDL_SetWindowSize(window_, (wnd_rect_bfr_max_.right - wnd_rect_bfr_max_.left), (wnd_rect_bfr_max_.bottom - wnd_rect_bfr_max_.top));
			wnd_rect_bfr_max_.bottom = 0;
		}
		GetWindowRect(window_, window_rect_);
		window_size_[0] = window_rect_.right - window_rect_.left;
		window_size_[1] = window_rect_.bottom - window_rect_.top;
		resize_ = 9;
		update_needed_ = true;
		OnMove(0.0f, 0.0f);

		//RedrawWindow(window_handle_, 0, 0, RDW_FRAME);

		return 0;
}


/*
 * 	MyDropMenu::***
 */

MyDropMenu::MyDropMenu (std::string text, float start_x, float start_y, float scale, int zone_size[2]) : MyTypeMesh(text, start_x, start_y, scale, zone_size),
																								   back_(start_x, start_y, 0.0f, 0.0f, 1, zone_size){
	scale_ = scale;
	zone_size_[0] = zone_size[0];
	zone_size_[1] = zone_size[1];

	draw_items_ = false;

	max_x_ = dims_[2];
}

bool MyDropMenu::Check(float x, float y) {
	if(draw_items_)
	{
		for(auto item = items_.begin(); item != items_.end(); item++)
		{
			if((*item).Check(x, y))
			{
				std::cout << "***" << std::endl;
				signals_[ item - items_.begin() ].Fire();
				draw_items_ = false;
			}
		}
	}


	if(MyTypeMesh::Check(x, y))
	{
		draw_items_ = !draw_items_;
	} else
	{
		draw_items_ = false;
	}

	return false;
}

void MyDropMenu::Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]) {
	MyTypeMesh::Resize(start_x, start_y, size_x, size_y, zone_size);
	max_x_ = dims_[2];

	float free_place_y = 0.0f;

	for(auto item = items_.begin(); item != items_.end(); item++)
	{
		free_place_y = dims_[1];
		if(item != items_.begin())
		{
			free_place_y = (*(item - 1)).dims()[1];
		}

		free_place_y -= (64.0f * scale_ * (700.0f / zone_size[1]))/FONT_TEX_SIZE;

		(*item).Resize(start_x, free_place_y, 0.0f, 0.0f, zone_size);

		if((*item).dims()[2] > max_x_)
		{
			max_x_ = (*item).dims()[2];
		}
	}

	free_place_y -= 4.0f/zone_size[0];
	max_x_ += 8.0f/zone_size[0];
	back_.UpdateSize(dims_[0] - 4.0f/zone_size[0], free_place_y, max_x_, (dims_[1] - free_place_y), zone_size);

}

/*
 * 	MyGLView::***
 */

MyGLView::MyGLView(float start_x, float start_y, float size_x, float size_y, int zone_size[2]) : MyBaseElement(start_x, start_y, size_x, size_y, zone_size){
	glGenFramebuffers(1, &framebuffer_);
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer_);
	Renderer::CheckGLError("glBindFramebuffer");
	glGenTextures(1, &color_texture_);
	glBindTexture(GL_TEXTURE_2D, color_texture_);
	Renderer::CheckGLError("glBindTexture");
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dims_px_[2], dims_px_[3], 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	glGenTextures(1, &depth_texture_);
	glBindTexture(GL_TEXTURE_2D, depth_texture_);
	Renderer::CheckGLError("glBindTexture");
	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, dims_px_[2], dims_px_[3], 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, color_texture_, 0);
	glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_texture_, 0);

	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, NULL_BUFF);

	positions_[0] = dims_[0];				positions_[1] = dims_[1];				positions_[2] = 0.0f;
	tex_coords_[0] = 0.5f/dims_px_[3];		tex_coords_[1] = 0.5f/dims_px_[3];
	positions_[3] = dims_[0] + dims_[2];	positions_[4] = dims_[1];				positions_[5] = 0.0f;
	tex_coords_[2] =  1.0f - 0.5f/dims_px_[3];					tex_coords_[3] = 0.5f/dims_px_[3];
	positions_[6] = dims_[0] + dims_[2];	positions_[7] = dims_[1] + dims_[3];	positions_[8] = 0.0f;
	tex_coords_[4] = 1.0f - 0.5f/dims_px_[3];tex_coords_[5] = 1.0f - 0.5f/dims_px_[3];
	positions_[9] = dims_[0];				positions_[10] = dims_[1] + dims_[3];	positions_[11] = 0.0f;
	tex_coords_[6] =0.5f/dims_px_[3];					tex_coords_[7] = 1.0f - 0.5f/dims_px_[3];
}

MyGLView::MyGLView(const MyGLView& view){
	std::copy(view.positions_, &view.positions_[12], positions_);
	std::copy(view.tex_coords_, &view.tex_coords_[8], tex_coords_);

	glGenFramebuffers(1, &framebuffer_);
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer_);
	Renderer::CheckGLError("glBindFramebuffer");
	glGenTextures(1, &color_texture_);
	glBindTexture(GL_TEXTURE_2D, color_texture_);
	Renderer::CheckGLError("glBindTexture");
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dims_px_[2], dims_px_[3], 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	glGenTextures(1, &depth_texture_);
	glBindTexture(GL_TEXTURE_2D, depth_texture_);
	Renderer::CheckGLError("glBindTexture");
	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, dims_px_[2], dims_px_[3], 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, color_texture_, 0);
	glFramebufferTexture(GL_DRAW_FRAMEBUFFER,  GL_DEPTH_ATTACHMENT, depth_texture_, 0);

	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, NULL_BUFF);

}

void MyGLView::Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]) {
	MyBaseElement::Resize(start_x, start_y, size_x, size_y, zone_size);

	positions_[0] = dims_[0];				positions_[1] = dims_[1];
	positions_[3] = dims_[0] + dims_[2];	positions_[4] = dims_[1];
	positions_[6] = dims_[0] + dims_[2];	positions_[7] = dims_[1] + dims_[3];
	positions_[9] = dims_[0];				positions_[10] = dims_[1] + dims_[3];

	tex_coords_[0] = 0.5f/dims_px_[3];			tex_coords_[1] = 0.5f/dims_px_[3];
	tex_coords_[2] =  1.0f - 0.5f/dims_px_[3];	tex_coords_[3] = 0.5f/dims_px_[3];
	tex_coords_[4] = 1.0f - 0.5f/dims_px_[3];	tex_coords_[5] = 1.0f - 0.5f/dims_px_[3];
	tex_coords_[6] =0.5f/dims_px_[3];			tex_coords_[7] = 1.0f - 0.5f/dims_px_[3];

	glBindTexture(GL_TEXTURE_2D, color_texture_);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dims_px_[2], dims_px_[3], 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);

	glBindTexture(GL_TEXTURE_2D, depth_texture_);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, dims_px_[2], dims_px_[3], 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);

}

/*
 * 	MyIcon::***
 */

MyIcon::MyIcon(float start_x, float start_y, float size_x, float size_y, int icon, int zone_size[2]) : MyBaseElement(start_x, start_y, size_x, size_y, zone_size){
	positions_[0] = start_x;				positions_[1] = start_y + size_y;
	tex_coords_[0] = WI_COORDS[icon][0];	tex_coords_[1] = WI_COORDS[icon][1];

	positions_[3] = start_x;				positions_[4] = start_y;
	tex_coords_[2] = WI_COORDS[icon][2];	tex_coords_[3] = WI_COORDS[icon][3];

	positions_[6] = start_x + size_x;		positions_[7] = start_y + size_y;
	tex_coords_[4] = WI_COORDS[icon][4];	tex_coords_[5] = WI_COORDS[icon][5];

	positions_[9] = start_x + size_x;		positions_[10] = start_y;
	tex_coords_[6] = WI_COORDS[icon][6];	tex_coords_[7] = WI_COORDS[icon][7];

	for(int i = 0; i < 4; i++)
	{
		positions_[ i * 3 + 2 ] = 0.0f;
	}

}

//#include <fcntl.h>
//#include <io.h>
/*
void RedirectIOToConsole()
{
    int hConHandle;
    long lStdHandle;
    CONSOLE_SCREEN_BUFFER_INFO coninfo;
    FILE *fp;

	// allocate a console for this app
    AllocConsole();

	// set the screen buffer to be big enough to let us scroll text
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&coninfo);
    coninfo.dwSize.Y = MAX_CONSOLE_LINES;
    SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),coninfo.dwSize);

	// redirect unbuffered STDOUT to the console
    lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

    fp = fdopen(hConHandle, "w");

    *stdout = *fp;

    setvbuf(stdout, NULL, _IONBF, 0);

	// redirect unbuffered STDIN to the console

    lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

    fp = _fdopen(hConHandle, "r");
    *stdin = *fp;
    setvbuf(stdin, NULL, _IONBF, 0);

	// redirect unbuffered STDERR to the console
    lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

    fp = _fdopen(hConHandle, "w");

    *stderr = *fp;

    setvbuf(stderr, NULL, _IONBF, 0);

	// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
	// point to console as well
    ios::sync_with_stdio();

	system("color F0");
}
*/







MouseMove current_mouse = { 0.0, 0.0 };
MouseMove prev_mouse= { 0.0, 0.0 };

void Quit();

bool g_quit = false;

void ForceWindowUpdate()
{
	SDL_Event event1;
	event1.type = SDL_WINDOWEVENT_ENTER;
	SDL_PushEvent(&event1);
}

bool FireSignals(cSignal<int, float, float>& click_signal, cSignal<int, float, float>& release_signal, cSignal<int, float, float>& move_signal, cSignal< int, std::vector<unsigned char>& >& key_press_signal, cSignal<int, float, float>* right_click_signal, cSignal<int, bool>* wheel_signal, bool wait) {
	SDL_Event event;
	static SDL_Window* p_active_window = nullptr;
	static MyRect rect, rect2;
	static int mouse_x = 0, mouse_y = 0;
	static bool grabbed = false;
#ifdef __LINUX__
	static Window w;
	static Display* d = nullptr;
#endif
	static int last_x = 0, last_y = 0;

	static std::vector<unsigned char> pressed_keys;

	if(!p_active_window)
	{
		//cout << "errr\n";
	}

	//GetWindowRect(p_active_window, rect);

	static bool b = false;


	//SDL_GetMouseState(&x, &y);
	int x, y, xx, yy;

	if(p_active_window)
	{
#ifdef WIN32
		POINT p;
		GetCursorPos(&p);
		mouse_x = p.x;
		mouse_y = p.y;
#endif
#ifdef __LINUX__
		Window pp, ppp;
		unsigned int mask;

		XQueryPointer(d, w, &pp,
						&ppp, &mouse_x, &mouse_y, &x, &y,
						&mask);
#endif
		//SDL_WarpMouseInWindow(p_active_window, last_x, last_y);

		current_mouse.x = mouse_x;
		current_mouse.y = mouse_y;

		xx = current_mouse.x - prev_mouse.x;
		yy = current_mouse.y - prev_mouse.y;

		if(	abs(xx) > 0 ||
			abs(yy) > 0	)
		{

			if(grabbed)
			{
				move_signal.Fire(((float)xx)/(float)(rect.right - rect.left),
							      ((float)yy)/(float)(rect.bottom - rect.top));

				GetWindowRect(p_active_window, rect);
			}

			prev_mouse.x = mouse_x;
			prev_mouse.y = mouse_y;

		}


	}

	int num = 0;
	static bool can_wait = true;
	if(can_wait && wait)
	{
		SDL_Event event1;
		event1.type = SDL_MOUSEMOTION;
		if(!grabbed)
		while(event1.type == SDL_MOUSEMOTION)
		{
			SDL_WaitEvent(&event1);
		}
		SDL_PushEvent(&event1);

#ifdef WIN32
		POINT p;
		GetCursorPos(&p);
		mouse_x = p.x;
		mouse_y = p.y;
#endif
#ifdef __LINUX__
		Window pp, ppp;
		unsigned int mask;

		XQueryPointer(d, w, &pp,
						&ppp, &mouse_x, &mouse_y, &x, &y,
						&mask);
#endif

		prev_mouse.x = mouse_x;
		prev_mouse.y = mouse_y;
	}
	while(SDL_PollEvent(&event)) {
		num++;
		switch(event.type) {
		case SDL_MOUSEBUTTONDOWN:

			if(p_active_window == nullptr)
			{
#ifdef WIN32
				POINT p;
				GetCursorPos(&p);
				prev_mouse.x = p.x;
				prev_mouse.y = p.y;
#endif
			}

			p_active_window = SDL_GetWindowFromID(event.window.windowID);
			GetWindowRect(p_active_window, rect);
			last_x = event.motion.x;
			last_y = event.motion.y;

			grabbed = true;

			if(event.button.button == SDL_BUTTON_LEFT)
			{
				click_signal.Fire((((float)event.motion.x)/(rect.right - rect.left))*2.0f - 1.0f, (-((float)event.motion.y)/(rect.bottom - rect.top))*2.0f + 1.0f);
			} else
			if(event.button.button == SDL_BUTTON_RIGHT)
			{
				if(right_click_signal)
				{
					right_click_signal->Fire((((float)event.motion.x)/(rect.right - rect.left))*2.0f - 1.0f, (-((float)event.motion.y)/(rect.bottom - rect.top))*2.0f + 1.0f);
				}
			}
			can_wait = false;
			break;
		case SDL_MOUSEBUTTONUP:
			grabbed = false;
			GetWindowRect(p_active_window, rect);

			release_signal.Fire((((float)event.motion.x)/(rect.right - rect.left))*2.0f - 1.0f, (-((float)event.motion.y)/(rect.bottom - rect.top))*2.0f + 1.0f);
			can_wait = true;
			break;
		case SDL_KEYDOWN:
			if(event.key.keysym.sym == SDLK_LCTRL)
			{
				event.key.keysym.sym = 17;
			}
			if(event.key.keysym.sym == SDLK_LSHIFT || event.key.keysym.sym == SDLK_RSHIFT)
			{
				event.key.keysym.sym = 16;
			}
			b = true;
			//cout << "key: " << (int)event.key.keysym.sym << endl;
			if(!pressed_keys.empty())
			for(auto key = pressed_keys.begin(); key != pressed_keys.end(); key++)
			{
				if(*key == event.key.keysym.sym)
				{
					b = false;
				}
				//cout << "key: " << *key << endl;
			}

			if(b)
			{
				pressed_keys.push_back(event.key.keysym.sym);
			}

			key_press_signal.Fire(pressed_keys);
			can_wait = false;
			break;
		case SDL_KEYUP:
			if(event.key.keysym.sym == SDLK_LCTRL)
			{
				event.key.keysym.sym = 17;
			}
			if(event.key.keysym.sym == SDLK_LSHIFT || event.key.keysym.sym == SDLK_RSHIFT)
			{
				event.key.keysym.sym = 16;
			}
			if(!pressed_keys.empty())
			{
			auto key = pressed_keys.begin();
			while(key != pressed_keys.end())
			{
				if(*key == event.key.keysym.sym)
				{
					//cout << "same key: " << *key << endl;
					key = pressed_keys.erase(key);
					//key--;
				} else
				{
					key++;
				}
			}
			}
			key_press_signal.Fire(pressed_keys);

			if(pressed_keys.empty())
			{
				can_wait = true;
			}

			break;
		case SDL_QUIT:
			/* Handle quit requests (like Ctrl-c). */
			//Quit();
			break;
		case SDL_MOUSEMOTION:


			break;
		case SDL_MOUSEWHEEL:
			if(wheel_signal)
			if(event.wheel.y > 0)
			{
				wheel_signal->Fire(true);
			} else
			{
				wheel_signal->Fire(false);
			}
			break;
		case SDL_WINDOWEVENT_ENTER:
		case SDL_WINDOWEVENT_SHOWN:
		case SDL_WINDOWEVENT_EXPOSED:
			//p_active_window = SDL_GetWindowFromID(event.window.windowID);
			//GetWindowRect(p_active_window, rect);

			//system("pause");

			grabbed = false;

#ifdef __LINUX__
			SDL_SysWMinfo i;
			SDL_VERSION(&i.version);
			if(SDL_GetWindowWMInfo(p_active_window, &i))
			{
				w = i.info.x11.window;
				d = i.info.x11.display;
			}
#endif
			break;
		}
	}
	//cout << num << endl;

}
/*
bool FireSignals(HWND hWnd, unsigned int message, WPARAM wParam, cSignal<int, float, float>& click_signal, cSignal<int, float, float>& release_signal, cSignal<int, float, float>& move_signal) {

	
	switch(message) {
		case WM_LBUTTONDOWN:
		switch (wParam)
        {
		case MK_LBUTTON:
			SetCapture(hWnd);

			RECT rect;
			GetWindowRect(hWnd, &rect);

			POINT p;

			if (GetCursorPos(&p))
			{
				ScreenToClient(hWnd,&p);

				current_mouse.x = (float)p.x;
				current_mouse.y = (float)p.y;

				prev_mouse.x = (float)p.x;
				prev_mouse.y = (float)p.y;
			}
			
			click_signal.Fire(((current_mouse.x)/(rect.right - rect.left))*2.0f - 1.0f, (-(current_mouse.y)/(rect.bottom - rect.top))*2.0f + 1.0f);

			return true;
		}
		break;
		case WM_MOUSEMOVE:
		

		RECT rect;
		GetWindowRect(hWnd, &rect);

		POINT p, p2;

		if (GetCursorPos(&p))
		{
			p2 = p;
			ScreenToClient(hWnd,&p);
				
			current_mouse.x = (float)p.x;
			current_mouse.y = (float)p.y;

			move_signal.Fire((current_mouse.x - prev_mouse.x)/(float)((float)rect.right - rect.left),
							  (current_mouse.y - prev_mouse.y)/(float)((float)rect.bottom - rect.top));
		
		}

		ScreenToClient(hWnd,&p2);
		prev_mouse.x = static_cast<float>(p2.x);
		prev_mouse.y = static_cast<float>(p2.y);

		break;

		case WM_LBUTTONUP:

		ReleaseCapture();
		ShowCursor(true);
		
		
		if (GetCursorPos(&p))
		{
			ScreenToClient(hWnd,&p);

			current_mouse.x = (float)p.x;
			current_mouse.y = (float)p.y;

			prev_mouse.x = (float)p.x;
			prev_mouse.y = (float)p.y;
		}

		GetWindowRect(hWnd, &rect);

		move_signal.Fire(0.0f, 0.0f);

		release_signal.Fire(((current_mouse.x)/(rect.right - rect.left))*2.0f - 1.0f, (-(current_mouse.y)/(rect.bottom - rect.top))*2.0f + 1.0f);

		break;
		default:
			return false;
	}

	return false;

}
*/

MyEditBox::MyEditBox(string text, float start_x, float start_y, float size_x, float size_y, float scale, int zone_size[2], char flags) : MyBaseElement(start_x, start_y, size_x, size_y, zone_size),
																																		   box_(start_x + 4.0f / zone_size[0], start_y, size_x, size_y, zone_size, true),
																																		   cursor_("|", 0.0f, 0.0f, scale, zone_size),
																																		   back_(start_x, start_y, size_x, size_y, 1, zone_size){

		scale_ = scale;
		zone_size_[0] = zone_size[0];
		zone_size_[1] = zone_size[1];
		current_line_ = 0;
		current_char_ = 0;
		focused_ = false;

		flags_.set = flags;

		//cursor_.reset(new MyTypeMesh("|", 0.0f, 0.0f, scale, zone_size));

		//back_.reset(new MyWinFrame(start_x, start_y, size_x, size_y, 1, zone_size));

		//box_.reset(new MyLinearLayout(start_x + 4.0f / zone_size[0], start_y, size_x, size_y, zone_size, true));
		lines_.reserve(128);

		MyTypeMesh new_line(text, start_x, start_y, scale, zone_size);
		lines_.push_back(new_line);
		lines_text_.push_back(text);
		box_.AddElement(&lines_.back());

	}

void MyEditBox::Clear(){
	lines_.clear();
	MyTypeMesh new_line("", 0.0f, 0.0f, scale_, zone_size_);
	lines_text_.clear();
	lines_.push_back(new_line);
	lines_text_.push_back("");
	//box_.reset(new MyLinearLayout(dims_[0], dims_[1], dims_[2], dims_[3], zone_size_, true));
	box_ = MyLinearLayout(dims_[0], dims_[1], dims_[2], dims_[3], zone_size_, true);
	box_.AddElement(&lines_.back());
	current_line_ = 0;
	current_char_ = 0;
}

string MyEditBox::GetLine(int line) {

	return lines_text_[line];

}

void MyEditBox::AddLine(string text) {

		if(! flags_.multiline)
		{
			return;
		}

		MyTypeMesh new_line(text, 0.0f, 0.0f, scale_, zone_size_);
		lines_.push_back(new_line);
		lines_text_.push_back(text);
		box_.AddElement(&lines_.back());
		current_line_++;

}

void MyEditBox::DeleteLine(int line) {

	if(line == 0)
	{
		lines_[ line ] = MyTypeMesh("", 0.0f, 0.0f, scale_, zone_size_);
		//lines_.erase(lines_.begin() + line);
		lines_text_[line] = "";
		
		for(auto line = lines_.begin(); line != lines_.end(); line++)
		{
			box_.ReplaceElement(&(*line), line - lines_.begin());
		}
	}

	box_.Resize(dims_[0], dims_[1], dims_[2], dims_[3], zone_size_);
	cursor_.Move(lines_[ current_line_ ].dims()[0], lines_[ current_line_ ].dims()[1], zone_size_);
	//lines_.erase(lines_.begin() + line - 1);
	current_char_ = 0;
	current_line_ = line;

}

void MyEditBox::InsertLine(string text) {

		if(! flags_.multiline)
		{
			return;
		}

		current_line_++;

		MyTypeMesh new_line(text, 0.0f, 0.0f, scale_, zone_size_);

		lines_.insert(lines_.begin() + current_line_, new_line);

		lines_text_.insert(lines_text_.begin() + current_line_, text);

		for(auto line = lines_.begin(); line != lines_.end(); line++)
		{
			box_.ReplaceElement(&(*line), line - lines_.begin());
		}

	}

void MyEditBox::Listen(vector<unsigned char>& keys) {

		if(!focused_)
		{
			return;
		}

		static unsigned int last_count = 0;

		char kkey;

		if(!keys.empty())
		{

			kkey = keys[0];
			bool b = false;

		for(auto key = keys.begin(); key != keys.end(); key++)
		{
			switch(*key)
			{
			//case VK_SHIFT:
			//case SDLK_LSHIFT:
			//case SDLK_RSHIFT:
			case 16:
				b = true;
				break;
			case SDLK_BACKSPACE:
				DeleteChar();
				break;
			case SDLK_RETURN:
				//AddLine(" ");

				InsertLine("");

				//current_line_++;
				current_char_ = 0;

				box_.Resize(dims_[0], dims_[1], dims_[2], dims_[3], zone_size_);

				cursor_.Move(lines_[ current_line_ ].dims()[0], lines_[ current_line_ ].dims()[1], zone_size_);

				return;
				break;
			default:
				kkey = *key;
			}
		}
		
		if(!b)
		{
			//kkey = tolower(kkey);
		} else
		{
			//cout << (int)kkey << endl;
			/*if(kkey == -67)
			{
				kkey = 127;
			} else*/
			if(kkey == '-')
			{
				kkey = '_';
			} else
			if(kkey == '=')
			{
				kkey = '+';
			} else
			{
				kkey = toupper(kkey);
			}
		}

		if( keys.size() != last_count - 1)
		{
			AddChar(kkey);
			last_count = keys.size();
		} else
		{
			last_count = 0;
			/*same_count++;
			if(same_count > 1)
			{
				AddChar(kkey);
				last_key = kkey;
				same_count = 0;
			}*/
		}

		}
	}

void MyEditBox::AddChar(unsigned char s) {

		switch(s) {
		case 191:
			s = '0' - 1;
			break;
		case 190:
			if(!(flags_.char_allowed || flags_.float_allowed)) return;
			s = 46;
			break;
		case 188:
			if(!flags_.char_allowed) return;
			s = 44;
			break;
		default:
			if(((s == ' ' || (s >= 'A' && s <= 'z')) && (flags_.char_allowed)) ||
				((s == '.' || s == '-' || s == '=' || s == '+' || s == '/' || (s >= '0' && s <= '9')) && (flags_.int_allowed || flags_.float_allowed)))
			{} else
			{		
				cout << "no " << (int)s << endl;
				return;
			}
		}

		lines_text_[ current_line_ ].insert(current_char_, reinterpret_cast<char*>(&s), 1);

		//lines_text_[ current_line_ ][ current_char_ ] = s;
		MyTypeMesh new_line(lines_text_[ current_line_ ], 0.0f, 0.0f, scale_, zone_size_);

		lines_[ current_line_ ] = new_line;
		//box_->ChangeElement(&lines_[ current_line_ ], current_line_);
		box_.ReplaceElement(&lines_[ current_line_ ], current_line_);

		current_char_++;

		box_.Resize(dims_[0] + 8.0f / zone_size_[0], dims_[1], dims_[2], dims_[3], zone_size_);

		float x;
		if(current_char_ < lines_text_[ current_line_ ].length())
		{
			x = (*lines_[ current_line_ ].positions())[current_char_ * 12];
			//x = lines_[ current_line_ ].dims()[0] + lines_[ current_line_ ].dims()[2];
		} else
		{
			x = lines_[ current_line_ ].dims()[0] + lines_[ current_line_ ].dims()[2];
		}

		//float cursor_pos[2] = { (*lines_[ current_line_ ].positions())[current_char_ * 12],
		float cursor_pos[2] = { x,
								lines_[ current_line_ ].dims()[1]};
		/*if(current_char_ >= lines_text_[ current_line_ ].length())
		{
			cursor_pos[0] = lines_[ current_line_ ].dims()[0] + lines_[ current_line_ ].dims()[2];
		}*/

		cursor_.Move(cursor_pos[0], cursor_pos[1], zone_size_);

	}

void MyEditBox::DeleteChar() {

		if(current_char_ < 1)
		{
			return;
		}

		lines_text_[ current_line_ ].erase(current_char_ - 1, 1);

		MyTypeMesh new_line(lines_text_[ current_line_ ], 0.0f, 0.0f, scale_, zone_size_);

		lines_[ current_line_ ] = new_line;
		//box_->ChangeElement(&lines_[ current_line_ ], current_line_);
		box_.ReplaceElement(&lines_[ current_line_ ], current_line_);

		current_char_--;

		box_.Resize(dims_[0], dims_[1], dims_[2], dims_[3], zone_size_);

		if(current_char_ == 0)
		{
			cursor_.Move(dims_[0], lines_[ current_line_ ].dims()[1], zone_size_);
			return;
		}

		float x;
		if(current_char_ < lines_text_[ current_line_ ].length())
		{
			x = (*lines_[ current_line_ ].positions())[current_char_ * 12];
		} else
		{
			x = lines_[ current_line_ ].dims()[0] + lines_[ current_line_ ].dims()[2];
		}

		//float cursor_pos[2] = { (*lines_[ current_line_ ].positions())[current_char_ * 12],
		float cursor_pos[2] = { x,
								lines_[ current_line_ ].dims()[1]};
		/*if(current_char_ >= lines_text_[ current_line_ ].length())
		{
			cursor_pos[0] = lines_[ current_line_ ].dims()[0] + lines_[ current_line_ ].dims()[2];
		}*/

		cursor_.Move(cursor_pos[0], cursor_pos[1], zone_size_);

	}

void MyEditBox::Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]) {

		MyBaseElement::Resize(start_x, start_y, size_x, size_y, zone_size);

		zone_size_[0] = zone_size[0];
		zone_size_[1] = zone_size[1];

		box_.Resize(start_x + 4.0f/zone_size[0], start_y, size_x, size_y, zone_size);

		back_.UpdateSize(start_x, start_y, size_x, size_y, zone_size);

	}

bool MyEditBox::Check(float x, float y) {

		if(MyBaseElement::Check(x, y))
		{
			focused_ = true;
			for(auto line = lines_.begin(); line != lines_.end(); line++)
			{
				vector<float>* p_pos = (*line).positions();
				if((*line).Check(x, y))
				{
					current_line_ = line - lines_.begin();

					for(auto point = p_pos->begin(); point != p_pos->end(); point += 4 * 3)
					{
						if(x < point[9])
						{
							current_char_ = (point - p_pos->begin()) / 12;
							cout << "current_char: " << current_char_ << endl;
							cursor_.Move(point[3], point[4], zone_size_);
							break;
						}
					} 

					return true;
				} else if(y < (*line).dims()[1] + (*line).dims()[3] && y > (*line).dims()[1])
				{
					current_line_ = line - lines_.begin();
					current_char_ = p_pos->size() / 12;
					cout << "current_char1: " << current_char_ << endl;
					if(current_char_ != 0)
					{
						cursor_.Move(*(p_pos->end() - 3), (*line).dims()[1], zone_size_);
					} else
					{
						cursor_.Move(dims_[0], (*line).dims()[1], zone_size_);
					}
					break;
				}
			}

			

		} else
		{
			focused_ = false;
			return false;
		}

		return false;

	}

void MyEditBox::Draw() {

		back_.Draw();

		glScissor(dims_px_[0], dims_px_[1], dims_px_[2], dims_px_[3]);
		glEnable(GL_SCISSOR_TEST);

		box_.Draw();

		if(focused_)
		{
			cursor_.Draw();
		}

		glDisable(GL_SCISSOR_TEST);


	}


/*************************************************************************************/

MyButton::MyButton(string text, float start_x, float start_y, float size_x, float size_y, int zone_size[2]) : MyBaseElement(start_x, start_y, size_x, size_y, zone_size),
																							 button_frame_(start_x, start_y, size_x, size_y, 1, zone_size),
																							 button_frame_pressed_(start_x, start_y, size_x, size_y, 2, zone_size),
																							 text_(text, start_x, start_y, 0.8f, zone_size),
																							 pressed_(false){

		//button_frame_.reset(new MyWinFrame(start_x, start_y, size_x, size_y, 1, zone_size));
		//button_frame_pressed_.reset(new MyWinFrame(start_x, start_y, size_x, size_y, 2, zone_size));

		//text_.reset(new MyTypeMesh(text, start_x, start_y, 0.8f, zone_size));
		text_.Move(start_x + 0.5f*size_x, start_y + 0.55f*size_y, zone_size);
		text_.Centrate();
	}

bool MyButton::Check(float x, float y) {
					

		if(MyBaseElement::Check(x, y))
		{
			std::cout << "pressed!!! : " << x << " " << y << std::endl;
			if(!pressed_)
			{
				pressed_ = true;
			} else
			{
				pressed_ = false;
				press_signal_.Fire();
			}
			return true;
		}

		pressed_ = false;
		return false;
	}

void MyButton::Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]) {
		MyBaseElement::Resize(start_x, start_y, size_x, size_y, zone_size);
		
		button_frame_.UpdateSize(start_x, start_y, size_x, size_y, zone_size);
		button_frame_pressed_.UpdateSize(start_x, start_y, size_x, size_y, zone_size);

		text_.Move(start_x + 0.5f*size_x, start_y + 0.55f*size_y, zone_size);
		text_.Centrate();
	}

void MyButton::Draw() {

		if(!pressed_)
		{
			button_frame_.Draw();
		} else
		{
			button_frame_pressed_.Draw();
		}

		glScissor(dims_px_[0], dims_px_[1], dims_px_[2], dims_px_[3]);
		glEnable(GL_SCISSOR_TEST);
		text_.Draw();
		glDisable(GL_SCISSOR_TEST);

	}


/*************************************************************************************/

int dummy_zone[2] = { 500, 500 };

MyEditField::MyEditField(string name, char flags) : 	name_(name, 0.0f, 0.0f, 0.8f, dummy_zone),
														edit_box_("", 0.0f, 0.0f, 0.1f, 0.1f, 0.8f, dummy_zone, flags & ~MULTILINE){

	//int dummy_zone[2] = { 500, 500 };
	//name_.reset(new MyTypeMesh(name, 0.0f, 0.0f, 0.8f, dummy_zone));
	//name_ = MyTypeMesh(name, 0.0f, 0.0f, 0.8f, dummy_zone);
	//edit_box_ = MyEditBox("", 0.0f, 0.0f, 0.1f, 0.1f, 0.8f, dummy_zone, flags /*& ~MULTILINE*/);

	//changed_slot_.AssignFunction(this, &MyEditField::OnChange);

}
MyEditField::~MyEditField() {
	
}

void MyEditField::Resize(float start_x, float start_y, float size_x, float size_y, int zone_size[2]) {

	MyBaseElement::Resize(start_x, start_y, size_x, size_y, zone_size);

	name_.Resize(start_x, start_y, size_x, size_y, zone_size);

	edit_box_.Resize(start_x + name_.dims()[2], start_y, size_x - name_.dims()[2], size_y, zone_size);

}

bool MyEditField::Check(float x, float y){
	if(!MyBaseElement::Check(x, y))
	{
		edit_box_.set_focus(false);
		return false;
	}

	edit_box_.Check(x, y);

	return true;
}

void MyEditField::Draw() {
	edit_box_.Draw();
	name_.Draw();
}

void MyEditField::Listen(vector<unsigned char>& keys){
	if(edit_box_.focused())
	if(std::find(keys.begin(), keys.end(), (unsigned char)SDLK_RETURN) != keys.end())
	{
		changed_signal.Fire(edit_box_.GetLine(0));
		edit_box_.set_focus(false);
	}

	edit_box_.Listen(keys);
}

void MyEditField::SetValue(string str){
	//cout << str << endl;
	edit_box_.Clear();
	for(auto ch : str)
	{
		edit_box_.AddChar(static_cast<unsigned char>(ch));
	}

}

string MyEditField::GetValue(){
	return edit_box_.GetLine(0);
}

/*************************************************************************************/
